package context

import (
	"encoding/json"
	"net/http"
	"time"

	"yingsheng.com/go-api-server/config"
	"yingsheng.com/go-api-server/errors"
	"yingsheng.com/go-api-server/module"
)

type Context struct {
	Module      *module.Client
	Request     *Request
	Response    *Response
	UserSession *Session
	isDev       bool
	chainInfo   ChainInfo
	RequestTime time.Time
}

func (c *Context) NewRequestInfo(action string) map[string]string {
	return c.Request.Info.NewRequestInfo(action)
}

// 创建新的上下文对象
func NewContext(moduleClient *module.Client, isDev bool) *Context {
	return &Context{
		isDev:       isDev,
		Module:      moduleClient,
		Request:     NewRequest(),
		Response:    NewResponse(),
		UserSession: NewSession(),
		chainInfo: ChainInfo{
			Host: config.Configer.ApiConf.Server + ":" + config.Configer.ApiConf.HttpPort,
		},
	}
}

// 重置上下文对象
func (c *Context) Reset(httpReq *http.Request, httpRes http.ResponseWriter) {
	c.RequestTime = time.Now()

	c.Request.Reset(c, httpReq)
	c.Response.Reset(c, httpRes)
	c.UserSession.Reset(c)

	c.chainInfo.Reset(c)
}

// 当前是否处于开发模式
func (c *Context) IsDev() bool {
	return c.isDev
}

// 中断请求流程
func (c *Context) Stop() {
	panic(errors.StopError)
}

func (c *Context) ChainMemo(str string) {
	c.chainInfo.Memo += str + "\n"
}

func (c *Context) ChainError(str string) {
	c.chainInfo.ErrorInfo = str
}

func (c *Context) ChainResponse(str string) {
	c.chainInfo.Response = str
}

func (c *Context) ChainToJson() []byte {
	c.chainInfo.ResponseTime = int(time.Now().Sub(c.RequestTime).Nanoseconds() / 1000)

	j, e := json.Marshal(&c.chainInfo)
	if e == nil {
		return j
	} else {
		b := []byte(`{"error":"Json Marshal error: ` + e.Error() + `"}`)
		return b
	}
}
